﻿/*! @file
********************************************************************************
<PRE>
文 件 名    : SrcFile.cs
说    明    : 转换 源代码文件
作    者    : 汪泽然
--------------------------------------------------------------------------------
备    注    : VisualStudio2005.CSharp
--------------------------------------------------------------------------------
修改记录: 
 * 日    期    版  本    修改人    修改内容 
 * 2009-7-9    0.1.0    汪泽然    完成基本转换功能
 * 2009-7-21   0.1.1    汪泽然    修复有命名空间时，Web.config文件转换失败的问题
 * 2009-8-13   0.1.2    汪泽然    完善对Web.config要删除节点的判断
</PRE>
********************************************************************************
* 版权所有(c) 2008 ~ 2009, 汪泽然, 保留所有权利
*******************************************************************************/
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Xml.XPath;
using Wangzeran.Transform.Core.ITransform;
using Wangzeran.Transform.Core.TransformException;
using Wangzeran.Transform.Core.Util;
using Wangzeran.Transform.Core.Support;

namespace Wangzeran.Transform.PlugIn.VisualStudio2005.CSharp
{
    /// <summary>
    /// 转换 源代码文件
    /// </summary>
    public class SrcFile : BaseSrcFile
    {

        #region Common Variables

        /// <summary>
        /// 要删除的命名空间列表
        /// </summary>
        private string[] _namespaceList = new string[] { "System.Core", 
            "System.Linq", 
            "System.Data.DataSetExtensions" };

        /// <summary>
        /// CS文件
        /// </summary>
        private const string TYPE_CS = "cs";
        /// <summary>
        /// Web.Config文件
        /// </summary>
        private const string TYPE_WEBCONFIG = "config";

        #endregion


        #region BaseSrcFile成员

        /// <summary>
        /// 转换 源代码文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        /// <exception cref="TransformFailureException">转换失败的异常</exception>
        public override bool Transform(string filePath)
        {
            try
            {
                TransformSrcFile(filePath);
                TransformWebConfig(filePath);
                return true;
            }
            catch (TransformFailureException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new TransformFailureException(filePath, ex.Message);
            }
        } 

        #endregion


        #region Assist Method

        /// <summary>
        /// 转换源代码文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        /// <exception cref="TransformFailureException">转换失败的异常</exception>
        private bool TransformSrcFile(string filePath)
        {
            try
            {
                if (TransformUtil.GetFileExt(filePath) != TYPE_CS)
                {
                    return false;
                }
                else
                {

                    StringBuilder sb = new StringBuilder();

                    sb.Append(TransformUtil.GetFileContent(filePath));

                    // 循环替换源代码文件中的.Net 3.5的命名空间
                    foreach (string item in _namespaceList)
                    {
                        sb.Replace("using " + item + ";", String.Empty);
                    }

                    string content = sb.ToString();

                    TransformUtil.WriteFileContent(filePath, content);

                    return true;

                }
            }
            catch (Exception ex)
            {
                throw new TransformFailureException(filePath, ex.Message);
            }
        }

        /// <summary>
        /// 转换 Web.Config文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        /// <exception cref="TransformFailureException">转换失败的异常</exception>
        private bool TransformWebConfig(string filePath)
        {
            try
            {
                if (TransformUtil.GetFileExt(filePath) != TYPE_WEBCONFIG)
                {
                    return true;
                }
                else
                {

                    XmlDocument doc = new XmlDocument();
                    doc.Load(filePath);

                    using (XmlTextWriter tr = new XmlTextWriter(filePath, Encoding.UTF8))
                    {
                        try
                        {
                            // 如果是Web.config文件，则移除以下节点
                            foreach(XmlNode node in doc.ChildNodes)
                            {
                                if (node.Name.ToLower() == "configuration")
                                {
                                    foreach(XmlNode rootNode in node.ChildNodes)
                                    {
                                        if (rootNode.Name.ToLower() == "configsections")
                                        {
                                            // ConfigSections节点
                                            DeleteConfigSections(rootNode.ChildNodes);
                                        }
                                        else if (rootNode.Name.ToLower() == "system.web")
                                        {
                                            // System.Web节点
                                            foreach(XmlNode childNode in rootNode.ChildNodes)
                                            {
                                                if (childNode.Name.ToLower() == "compilation")
                                                {
                                                    DeleteCompilation(childNode.ChildNodes);
                                                }
                                                else if (childNode.Name.ToLower() == "pages")
                                                {
                                                    DeletePages(childNode.ChildNodes);
                                                }
                                                else if (childNode.Name.ToLower() == "httphandlers")
                                                {
                                                    DeleteHttpHandlers(childNode.ChildNodes);
                                                }
                                                else if (childNode.Name.ToLower() == "httpmodules")
                                                {
                                                    DeleteHttpModules(childNode.ChildNodes);
                                                }
                                            }
                                        }
                                        else if (rootNode.Name.ToLower() == "system.codedom")
                                        {
                                            // System.CodeDom节点
                                            foreach (XmlNode childNode in rootNode.ChildNodes)
                                            {
                                                if (childNode.Name.ToLower() == "compilers")
                                                {
                                                    DeleteCompilers(childNode.ChildNodes);
                                                }
                                            }
                                        }
                                        else if (rootNode.Name.ToLower() == "system.webserver")
                                        {
                                            // System.WebServer节点
                                            foreach (XmlNode childNode in rootNode.ChildNodes)
                                            {
                                                if (childNode.Name.ToLower() == "validation")
                                                {
                                                    childNode.RemoveAll();
                                                }
                                                else if (childNode.Name.ToLower() == "modules")
                                                {
                                                    DeleteModules(childNode.ChildNodes);
                                                }
                                                else if (childNode.Name.ToLower() == "handlers")
                                                {
                                                    DeleteHandlers(childNode.ChildNodes);
                                                }
                                            }
                                        }
                                        else if (rootNode.Name.ToLower() == "runtime")
                                        {
                                            // Runtime节点
                                            foreach (XmlNode childNode in rootNode.ChildNodes)
                                            {
                                                if (childNode.Name.ToLower() == "assemblybinding")
                                                {
                                                    DeleteRuntime(childNode.ChildNodes);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        finally
                        {
                            tr.Formatting = Formatting.Indented;
                            doc.WriteContentTo(tr);
                        }
                    }

                    return true;
                }
            }
            catch (Exception ex)
            {
                throw new TransformFailureException(filePath, ex.Message);
            }
        }


        #region Process Web.Config

        /// <summary>
        /// 移除空节点
        /// </summary>
        /// <param name="node"></param>
        private void CleanEmptyNode(XmlNode node, ref int index)
        {
            //if (node.ChildNodes.Count == 0)
            //{
            //    node.ParentNode.RemoveChild(node);
            //    index--;
            //}
        }


        #region configSections

        /// <summary>
        /// 移除ConfigSections节点的信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteConfigSections(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if ((nodes[i].Name == "sectionGroup"
                    || nodes[i].Name == "section")
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteConfigSections(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        #endregion


        #region System.Web

        /// <summary>
        /// 移除compilation节点的信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteCompilation(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "add"
                    && nodes[i].Attributes["assembly"] != null
                    && nodes[i].Attributes["assembly"].Value.Contains("Version=3.5.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteCompilation(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }


        /// <summary>
        /// 移除pages节点的信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeletePages(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "add"
                    && nodes[i].Attributes["assembly"] != null
                    && nodes[i].Attributes["assembly"].Value.Contains("Version=3.5.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeletePages(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }


        /// <summary>
        /// 移除httpHandlers节点的信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteHttpHandlers(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "remove"
                    && nodes[i].Attributes["verb"].Value == "*"
                    && nodes[i].Attributes["path"].Value == "*.asmx")
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else if (nodes[i].Name == "add"
                    && nodes[i].Attributes["type"] != null
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteHttpHandlers(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }


        /// <summary>
        /// 移除httpModules节点的信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteHttpModules(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "add"
                    && nodes[i].Attributes["name"].Value == "ScriptModule"
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeletePages(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        #endregion


        #region System.CodeDom

        /// <summary>
        /// 删除Compilers节点信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteCompilers(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "compiler"
                    || nodes[i].Attributes["type"].Value.Contains("Version=2.0.0.0"))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteCompilers(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        #endregion


        #region System.WebServer

        /// <summary>
        /// 删除Modules节点信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteModules(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "remove"
                    && (nodes[i].Attributes["type"] != null
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0")))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else if (nodes[i].Name == "add"
                    && (nodes[i].Attributes["type"] != null
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0")))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteModules(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        /// <summary>
        /// 删除Handlers节点信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteHandlers(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "remove"
                    && (nodes[i].Attributes["type"]!=null 
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0")))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else if (nodes[i].Name == "add"
                    && (nodes[i].Attributes["type"] != null
                    && nodes[i].Attributes["type"].Value.Contains("Version=3.5.0.0")))
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteHandlers(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        #endregion


        #region Runtime

        /// <summary>
        /// 删除Runtime节点信息
        /// </summary>
        /// <param name="nodes"></param>
        private void DeleteRuntime(XmlNodeList nodes)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i].Name == "assemblyIdentity"
                    && nodes[i].Attributes["publicKeyToken"].Value == "31bf3856ad364e35")
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else if (nodes[i].Name == "bindingRedirect"
                    && nodes[i].Attributes["newVersion"].Value == "3.5.0.0")
                {
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
                    i--;
                }
                else
                {
                    DeleteRuntime(nodes[i].ChildNodes);
                    CleanEmptyNode(nodes[i], ref i);
                }
            }
        }

        #endregion


        #endregion


        #endregion
    }
}
